<?php
/**
 * Created by PhpStorm.
 * User: Huyang
 * Date: 2016/9/21
 * Time: 18:01
 */

namespace App\Http\Repositories\Eloquent;


use App\Util\Helper;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;

class Orm extends Model
{

    protected $isCache = false;
    protected $cacheKey = 'id';
    protected $cacheExpire = 0;
    protected $prefixTable = 'table_';

    public static function boot()
    {
        parent::boot();
        static::deleted(function ($model) {
            if (true === $model->isCache) {
                $key = $model->cacheKey;
                $model->clearKey($model->$key);
            }

        });
        static::saved(function ($model) {
            if (true === $model->isCache) {
                $key = $model->cacheKey;
                $model->refreshRow($model->$key);
            }
        });
    }

    /**
     * 整个表缓存
     * @param int    $id
     * @param string $field
     * @param string $primary
     * @return array|\Illuminate\Database\Eloquent\Collection|mixed|string|static[]
     */
    public static function map($id = 0, $field = '', $primary = 'id') {
        $key = $data = null;
        $table = (new static)->getTable();
        if ($id) {
            if (is_numeric($id)) {
                $key = 'cache_table_'.$table.'_id_'.$id;
            } else {
                if (!is_array($id) || !Helper::sqlId(implode(',',$id))) {
                    return false;
                }
            }
        } else {
            $key = 'cache_table_'.$table;
        }
        if ($key) {
           // $data = Redis::get($key);
            if (!$data) {
                $data = self::all();
                if ($data) {
                    $data = serialize($data->toArray());
                   // Redis::set($key, $data);
                }
            }
        } else {
            $query = self::query();
            $data = $query->whereIn($primary, $id)->get();
            if ($data->count()) {
                $data = $data->toArray();
            } else {
                $data = [];
            }
        }
        if ($data) {
            if ($key) {
                $data = unserialize($data);
            }
            if ($primary) {
                $data = Helper::arrayMapByKey($data, $primary);
            }
            if ($id) {
                if (is_array($id)) {
                    foreach ($data as $key => $val) {
                        if (!in_array($key, $id)) {
                            unset($data[$key]);
                        }
                    }
                } else {
                    if ($field) {
                        $data = isset($data[$id]) ? $data[$id][$field] : '';
                    } else {
                        $data = isset($data[$id]) ? $data[$id] : [];
                    }
                }
            } else {
                if ($field) {
                    $data = '';
                } else {
                    $data = Helper::arrayMapByKey($data);
                }
            }
        }
        return $data;
    }

    /**
     * 清空缓存
     */
    public function clearMap() {
        $table = (new static)->getTable();
        $key = 'cache_table_'.$table;
        Redis::set($key, null);
    }

    /**
     * 删除缓存
     * @param $val
     */
    public function clearKey($val)
    {
        Redis::del($this->table . ':' . $this->cacheKey . ':' . $val);
    }

    /**
     * 更新缓存
     * @param $val
     */
    public function refreshRow($val)
    {
        Redis::del($this->table . ':' . $this->cacheKey . ':' . $val);
        $query = $this->newQuery();
        $data = $query->where($this->cacheKey, $val)->first();
        if ($data) {
            $data = serialize($data->toArray());
            $this->cacheData($val, $data);
        }
    }

    /**
     * 查询详情缓存
     * @param        $val
     * @param string $key
     * @return bool|mixed
     */
    public function cacheRow($val, $key = '')
    {
        if (empty($key)) {
            $key = $this->cacheKey;
        }
        $data = Redis::get($this->table . ':' . $key . ':' . $val);
        if (!$data) {
            $query = $this->newQuery();
            $data = $query->where($key, $val)->first();
            if ($data) {
                $data = serialize($data->toArray());
                $this->cacheData($val, $data);
            } else {
                return false;
            }
        }
        return unserialize($data);
    }

    /**
     * 查询列表缓存
     * @param $val
     * @return array|mixed
     */
    public function cacheList($val)
    {
        $data = Redis::get($this->table . ':' . $this->cacheKey . ':' . $val);
        if (!$data) {
            $query = $this->newQuery();
            $data = $query->where($this->cacheKey, $val)->get();
            if ($data) {
                $data = serialize($data->toArray());
                $this->cacheData($val, $data);
            } else {
                return [];
            }
        }
        return unserialize($data);
    }

    /**
     * 配置缓存
     * @param $val
     * @param $data
     * @return mixed
     */
    public function cacheData($val, $data)
    {
        return (0 === $this->cacheExpire) ? Redis::set($this->table . ':' . $this->cacheKey . ':' . $val, $data) : Redis::setex($this->table . ':' . $this->cacheKey . ':' . $val, $this->cacheExpire, $data);
    }

    /**
     * @var array 间接性的关闭白名单
     */
    protected $guarded = ['id'];

    /**
     * 获取当前时间
     *
     * @return int
     */
    public function freshTimestamp() {
        return time();
    }

    /**
     * 避免转换时间戳为时间字符串
     *
     * @param DateTime|int $value
     * @return DateTime|int
     */
    public function fromDateTime($value) {
        return $value;
    }

    /**
     * 从数据库获取的为获取时间戳格式
     *
     * @return string
     */
    public function getDateFormat() {
        return 'U';
    }

    /**
     * 默认返回日期格式
     * @return mixed
     */
    public function getCreatedAtAttribute(){
        return date('d/m/Y H:i:s',$this->attributes['created_at']);
    }

    /**
     * 默认返回日期格式
     * @return mixed
     */
    public function getUpdatedAtAttribute(){
        return date('d/m/Y H:i:s',$this->attributes['updated_at']);
    }

}